/*
* ============================================================================
*  Name        : example_007.cpp
*  Part of     : Finite state machine examples
*  Description : Message exchange between two state machines
*  Version     : %version: %
*  
*
* ============================================================================
*/
#include "example_007.h"
#include "example_007.hxx" // State machine source code is here

/**
 * @file example_007.cpp
 *
 * @details
 * Message exchange between two state machines.
 *
 * @ingroup StateMachineExamples
 */
using namespace sea_examples;

// ----------------------------------------------------------------------------
// Create 2 state machines. Mutual poking each other 5 times and the exit.
// How to access event parameters in other methods of the same class. See Event class.
// ----------------------------------------------------------------------------
void sea_examples::launch_example_007( )
{
    SEA_TRACE_ENTRY( );

    {
        sea::ref< Friend > friend1;
        friend1 << NEW Friend;

        if ( friend1->create( 0, Friend_src ) != eOk ){ /* See Error codes */ }
        if ( friend1->start( StateMachine::RunAsync ) != eOk ){ /* See Error codes */ }

        sea::ref< Friend > friend2;
        friend2 << NEW Friend;

        if ( friend2->create( 0, Friend_src ) != eOk ){ /* See Error codes */ }
        if ( friend2->start( StateMachine::RunAsync ) != eOk ){ /* See Error codes */ }

        // Starts poking. No explicit event parameter is sent
        friend2->push_event( friend2->Ev_Ext_Poke( ), friend1.get( ) );

        // Both parent and child run in 'async' mode, so wait for the completion here
        friend1->wait_manager_to_finish( );
        friend2->wait_manager_to_finish( );
    }
    Engine::terminate( );
}

ACT_IMPL( Friend, poke_back )
{
    SEA_UNUSED_PARAM( );

    ASSERT_DEBUG( ACT_EVENT_PARAM( ) == event( )->as< void >( ) );

    SEA_TRACE( "...Ouch..." );

    // Some other function
    some_other_func( );

}

void Friend::some_other_func( )
{
    // To respond back to we need to know the type of the event originator
    Friend* originator = reinterpret_cast< Friend* >( event( )->as< StateMachine >( ) );
    
    // Poking back
    originator->push_event( originator->Ev_Ext_Poke( ), this );
}
